package com.superzlc.vjoy;

public class VJoy {

	private static VJoy vjoy;

	static {
		try {
			System.loadLibrary("vjoy4jni");
		} catch (UnsatisfiedLinkError e) {
			System.out.println("加载vjoy4jni.dll失败");
			e.printStackTrace();
		}
		 vjoy = new VJoy();
	}

	public static VJoy getInstance() {
		return vjoy;
	}

	private VJoy() {
	}

	// vJoy Device Stat
	public static final int VJD_STAT_OWN = 0;	// The  vJoy Device is owned by this application.
	public static final int VJD_STAT_FREE = 1;	// The  vJoy Device is NOT owned by any application (including this one).
	public static final int VJD_STAT_BUSY = 2;	// The  vJoy Device is owned by another application. It cannot be acquired by this application.
	public static final int VJD_STAT_MISS = 3;	// The  vJoy Device is missing. It either does not exist or the driver is down.
	public static final int VJD_STAT_UNKN = 4;	// Unknown

	// HID Descriptor definitions - Axes
	public static final int HID_USAGE_X		= 0x30;
	public static final int HID_USAGE_Y		= 0x31;
	public static final int HID_USAGE_Z		= 0x32;
	public static final int HID_USAGE_RX	= 0x33;
	public static final int HID_USAGE_RY	= 0x34;
	public static final int HID_USAGE_RZ	= 0x35;
	public static final int HID_USAGE_SL0	= 0x36;
	public static final int HID_USAGE_SL1	= 0x37;
	public static final int HID_USAGE_WHL	= 0x38;
	public static final int HID_USAGE_POV	= 0x39;

	// General driver data
	public native short GetvJoyVersion();
	public native boolean vJoyEnabled();
	public native String	GetvJoyProductString();
	public native String	GetvJoyManufacturerString();
	public native String	GetvJoySerialNumberString();
	public native boolean	DriverMatch(String  dllVer, String  drvVer);
	// void	RegisterRemovalCB(Object cb, Object data);
	public native boolean	vJoyFfbCap();	// Is this version of vJoy capable of FFB?
	public native int	GetvJoyMaxDevices();	// What is the maximum possible number of vJoy devices
	public native int	GetNumberExistingVJD();	// What is the number of vJoy devices currently enabled

	// vJoy Device properties
	public native int  GetVJDButtonNumber(int  devId);	// Get the number of buttons defined in the specified VDJ
	public native int  GetVJDDiscPovNumber(int  devId);	// Get the number of descrete-type POV hats defined in the specified VDJ
	public native int  GetVJDContPovNumber(int  devId);	// Get the number of descrete-type POV hats defined in the specified VDJ
	public native boolean  GetVJDAxisExist(int  devId, int  axis); // Test if given axis defined in the specified VDJ
	public native long  GetVJDAxisMax(int  devId, int  axis); // Get logical Maximum value for a given axis defined in the specified VDJ
	public native long  GetVJDAxisMin(int  devId, int  axis); // Get logical Minimum value for a given axis defined in the specified VDJ
	public native int	GetVJDStatus(int  devId);			// Get the status of the specified vJoy Device.
	public native boolean	isVJDExists(int  devId);					// TRUE if the specified vJoy Device exists
	public native int	GetOwnerPid(int  devId);					// Reurn owner's Process ID if the specified vJoy Device exists

	// Write access to vJoy Device - Basic
	public native boolean		AcquireVJD(int  devId);				// Acquire the specified vJoy Device.
	public native void		RelinquishVJD(int  devId);			// Relinquish the specified vJoy Device.
	public native boolean		UpdateVJD(int  devId, JoyStickPosition data);	// Update the position data of the specified vJoy Device.

	// Write access to vJoy Device - Modifyiers

	//// Reset functions
	public native boolean		ResetVJD(int  devId);			// Reset all controls to predefined values in the specified VDJ
	public native void		ResetAll();				// Reset all controls to predefined values in all VDJ
	public native boolean		ResetButtons(int  devId);		// Reset all buttons (To 0) in the specified VDJ
	public native boolean		ResetPovs(int  devId);		// Reset all POV Switches (To -1) in the specified VDJ

	//// Write data
	public native boolean		SetAxis(long value, int  devId, int  axis);		// Write Value to a given axis defined in the specified VDJ
	public native boolean		SetBtn(boolean value, int  devId, char nBtn);		// Write Value to a given button defined in the specified VDJ
	public native boolean		SetDiscPov(int value, int  devId, char nPov);	// Write Value to a given descrete POV defined in the specified VDJ
	public native boolean		SetContPov(long value, int  devId, char nPov);	// Write Value to a given continuous POV defined in the specified VDJ

	// Force Feedback (FFB) functions, ignore

	public static class JoyStickPosition {
		/// JOYSTICK_POSITION
		public byte		bDevice;	// Index of device. 1-based.
		public long 	wThrottle;
		public long 	wRudder;
		public long 	wAileron;

		public long 	wAxisX;
		public long 	wAxisY;
		public long 	wAxisZ;

		public long 	wAxisXRot;
		public long 	wAxisYRot;
		public long 	wAxisZRot;

		public long 	wSlider; // Slider
		public long 	wDial;   // Dial/Slider2
		public long 	wWheel;  //

		public long 	wAxisVX;
		public long 	wAxisVY;
		public long 	wAxisVZ;
		public long 	wAxisVBRX;
		public long 	wAxisVBRY;
		public long 	wAxisVBRZ;

		// 按钮
		public long  lButtons;	// 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed
		public long  lButtonsEx1; // Buttons 33-64
		public long  lButtonsEx2; // Buttons 65-96
		public long  lButtonsEx3; // Buttons 97-128

		// 帽子键
		public long	bHats;		// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
		public long	bHatsEx1;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
		public long	bHatsEx2;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
		public long	bHatsEx3;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch ŁONG lButtonsEx1; // Buttons 33-64

		public void setDevId(int devId) {
			bDevice = (byte)devId;
		}

		/**
		 * 设置按钮状态
		 * @param btn 按钮编号，从0开始
		 * @param pressed
		 */
		public void setButton(int btnNo, boolean pressed) {
			if (btnNo >= 0) {
				if (pressed) {
					if (btnNo <= 32) {
						lButtons |= 1 << btnNo;
					} else if (btnNo <= 64) {
						lButtonsEx1 |= 1 << (btnNo - 32);
					} else if (btnNo <= 96) {
						lButtonsEx2 |= 1 << (btnNo - 64);
					} else if (btnNo < 128) {
						lButtonsEx3 |= 1 << (btnNo - 96);
					} else {
					}
				} else {
					if (btnNo <= 32) {
						lButtons &= ~(1 << btnNo);
					} else if (btnNo <= 64) {
						lButtonsEx1 &= ~(1 << (btnNo - 32));
					} else if (btnNo <= 96) {
						lButtonsEx2 &= ~(1 << (btnNo - 64));
					} else if (btnNo < 128) {
						lButtonsEx3 &= ~(1 << (btnNo - 96));
					} else {
					}
				}
			}
		}

		// 设置轴状态，范围0-65535
		public void setX(long v) {
			wAxisX = v;
		}
		public void setY(long v) {
			wAxisY = v;
		}
		public void setZ(long v) {
			wAxisZ = v;
		}

		public void setRX(long v) {
			wAxisXRot = v;
		}
		public void setRY(long v) {
			wAxisYRot = v;
		}
		public void setRZ(long v) {
			wAxisZRot = v;
		}

		public void setSL0_wSlider(long v) {
			wSlider = v;
		}
		public void setSL1_wDial(long v) {
			wDial = v;
		}
		public void setWheel(long v) {
			wWheel = v;
		}

	}
}
